#include <iostream>
#include <memory>
#include <vector>

class MyClass
{
public:
    int g, h, f;

    MyClass(int g, int h) : g(g), h(h), f(g + h)
    {
        std::cout << "MyClass constructed\n";
    }
    ~MyClass() { std::cout << " MyClass destructed\n"; }
    void doSomething() { std::cout << "g =" << g << ",h=" << h << "\n"; }
};

struct Node
{
    int x, y;
    std::shared_ptr<Node> parent;
    int g, h, f;
    std::string name;
    Node() {}
    Node(int x_val, int y_val,
         std::shared_ptr<Node> par,
         int g_val, int h_val,
         std::string name)
        : x(x_val), y(y_val), parent(par), g(g_val), h(h_val), f(g_val + h_val), name(name)
    {
    }
};

void uniquePtrExample()
{
    std::cout << "\n unique_ptr Example:\n";
    // 独占所有权的智能指针
    // std::unique_ptr<MyClass> uniquePtr(new MyClass(1, 10));//容易忘记释放内存
    // uniquePtr.reset();//释放内存

    auto uniquePtr = std::make_unique<MyClass>(1, 10);
    uniquePtr->doSomething();
    // uniquePtr goes out of scope and MyClass is automatically destroyed
}

void sharedPtrExample()
{
    std::cout << "\n shared_ptr Example:\n";
    std::shared_ptr<std::vector<std::shared_ptr<MyClass>>> sharedptr_list =
        std::make_shared<std::vector<std::shared_ptr<MyClass>>>();
    // 共享指针
    std::shared_ptr<MyClass> sharedPtr1 = std::make_shared<MyClass>(2, 9);
    {
        std::shared_ptr<MyClass> sharedPtr2 = sharedPtr1; // 指向同一个内存地址，引用次数加1
        sharedPtr2->doSomething();
        sharedptr_list->push_back(sharedPtr2);
        // sharedPtr2 goes out of scope, but MyClass is not destroyed
    }
    sharedPtr1->doSomething();
    std::cout << "\n sharedPtr1 g=" << sharedPtr1->g;
    std::cout << " sharedPtr1 address=" << sharedPtr1.get() << "\n";

    sharedptr_list->push_back(sharedPtr1);
    // 获取指针为0的元素
    auto ptr_list = sharedptr_list.get();
    std::cout << "\n(*sharedptr_list.get())[0]=" << (*ptr_list)[0]->g << "\n";
    // 遍历
    for (const std::shared_ptr<MyClass> &ptr : *sharedptr_list)
    {
        std::cout << ptr << " ptr g=" << ptr->g << ",h=" << ptr->h << "\n";
    }
    // sharedPtr1 goes out of scope and MyClass is destroyed
}

void weakPtrExample()
{
    std::cout << "\n weak_ptr Example:\n";
    std::shared_ptr<MyClass> sharedPtr = std::make_shared<MyClass>(3, 8);
    // 不控制对象生命周期的指针
    std::weak_ptr<MyClass> weakPtr = sharedPtr;
    {
        if (std::shared_ptr<MyClass> lockedPtr = weakPtr.lock())
        {
            lockedPtr->doSomething();
        }
        else
        {
            std::cout << "Object has been destroyed\n";
        }
    }
    sharedPtr.reset(); // 释放内存
    if (auto lockedPtr = weakPtr.lock())
    {
        lockedPtr->doSomething(); // 共享指针已释放内存，这里不会执行输出
    }
    else
    {
        std::cout << "Object has been destroyed\n";
    }
}

void ptrExample()
{
    // 普通指针

    int var;                                                           // 未初始化
    int *ptr = nullptr;                                                // 指针，当前不指向任何有效内存地址
    int **pptr = nullptr;                                              // 指向指针的指针
    std::cout << "var 值为 :" << var << ",地址:" << &var << std::endl; // var值可能包含任何值，取决于内存位置之前的内容
    std::cout << "ptr 值为:" << ptr << std::endl;
    std::cout << "pptr 值为:" << pptr << std::endl;
    var = 3000;

    // 获取 var 的地址
    ptr = &var;

    // 使用运算符 & 获取 ptr 的地址
    pptr = &ptr;

    var++;
    std::cout << "var 值为 :" << var << ",地址:" << &var << std::endl;
    std::cout << "ptr 值为:" << ptr << ",*ptr:" << *ptr << std::endl;
    std::cout << "pptr 值为:" << pptr << ",**pptr:" << **pptr << std::endl;
}
void sharedPtrExample2()
{
    std::cout << "\n -------------\n";
    std::vector<std::shared_ptr<Node>> node_list;
    unsigned int mx,my;
    for (unsigned int dx = 0; dx <= 1; dx++)
    {
        for (unsigned int dy = 0; dy <= 1; dy++)
        {
            if (dx == 0 && dy == 0)
                continue;
            mx = static_cast<unsigned int>(dx);
            my = static_cast<unsigned int>(dy);
            auto node_ptr = std::make_shared<Node>(mx,my,nullptr,0,0,"name");
            std::cout << node_ptr->x << "," << node_ptr->y << "," << node_ptr.get() << std::endl;
            node_list.push_back(node_ptr);
        }
    }
    std::cout << "\n -------------\n";
}
int main()
{
    try
    {
        ptrExample();
        uniquePtrExample();
        sharedPtrExample();
        weakPtrExample();
        sharedPtrExample2();
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}